/*!
 * Copyright (C) 2020 - All Rights Reserved by
 * @author : ZhaoYanbo
 * @email  : zyb920@hotmail.com
 * @created: 2020-10-31
 * @version: 1.0.0.0
 *
 */

#include "particletimelinewidget.h"
#include <QMouseEvent>
#include <QPainter>
#include <QtDebug>

ParticleTimeLineWidget::ParticleTimeLineWidget(QWidget *parent)
    : QWidget(parent)
{
    m_space = 20;
    this->setMouseTracking(true);
}

ParticleTimeLineWidget::~ParticleTimeLineWidget()
{
    qDeleteAll(m_items);
    m_items.clear();
}

void ParticleTimeLineWidget::setEndDuration(int d)
{
    m_endDuration = d;
    update();
}

void ParticleTimeLineWidget::setCurDuration(int d)
{
    m_curDuration = d;
    update();
}

void ParticleTimeLineWidget::setPreviewEndDuration(int d)
{
    m_previewEndDuration = d;
}

bool ParticleTimeLineWidget::setItemDuration(int index, int d)
{
    auto *item = m_items.value(index, nullptr);
    if(item) {
        item->duration = d;
        update();
        return true;
    }
    return false;
}

bool ParticleTimeLineWidget::insert(int index, ParticleItemData *item)
{
    int len = m_items.length();
    if(index >= 0 && index <= len) {
        m_items.insert(index, item);
        return true;
    }
    return false;
}

void ParticleTimeLineWidget::setSelected(int index)
{
    m_selectedIndex = index;
    update();
}

void ParticleTimeLineWidget::setCanToNext(int index, bool ok)
{
    auto *item = m_items.value(index, nullptr);
    if(item) {
        item->toNext = ok;
        update();
    }
}

bool ParticleTimeLineWidget::canToNext(int index) const
{
    auto *item = m_items.value(index, nullptr);
    if(item) {
        return item->toNext;
    }
    return false;
}

bool ParticleTimeLineWidget::remove(int index)
{
    auto *item = m_items.value(index, nullptr);
    if(item)
    {
        m_items.removeOne(item);

        delete item;
        item = nullptr;

        update();
        return true;
    }
    return false;
}

bool ParticleTimeLineWidget::removeCurSelected()
{
    bool b = remove(m_selectedIndex);
    m_selectedIndex = -1;
    return b;
}

void ParticleTimeLineWidget::clear()
{
    int len = m_items.length();
    if(len > 1)
    {
        auto *item = m_items.first();
        m_items.removeFirst();

        qDeleteAll(m_items);
        m_items.clear();

        m_items.append(item);

        update();
    }
}

int ParticleTimeLineWidget::doCheckRect(const QPoint &qpos) const
{
    int index = -1;
    const int len = m_items.length();
    int dx = 0;
    for(int i=0; i<len; ++i)
    {
        auto *item = m_items[i];
        dx = item->duration * 1.0f / 100 * m_space;
        if(QRect(dx-m_space/2, 52, m_space, 100).contains(qpos))
        {
            index = i;
            break;
        }
    }
    return index;
}

void ParticleTimeLineWidget::mousePressEvent(QMouseEvent *e)
{
    e->accept();

    if(m_hoverIndex >= 0)
    {
        m_items[m_hoverIndex]->reverseNext();
        m_selectedIndex = m_hoverIndex;
    }
    else
    {
        m_selectedIndex = doCheckRect(e->pos());

        if(m_selectedIndex >= 0)
        {
            m_pressedDuration = m_items[m_selectedIndex]->duration;
        }
        m_pressedPosX = e->pos().x();
        m_bPressed = true;
    }

    update();
}

void ParticleTimeLineWidget::mouseMoveEvent(QMouseEvent *e)
{
    e->accept();

    if( !m_bPressed)
    {
        //检查hover index

        int index = -1;
        const int len = m_items.length();
        for(int i=0; i<len; ++i)
        {
            auto *item = m_items[i];

            QRect rect(item->duration * 1.0f / 100 * m_space - m_space/2, 52, m_space, 100);
            const int subW = rect.width() - 4;
            QRect subRect(rect.x() + 2,
                          rect.y() + (rect.height() - subW) / 2,
                          subW,
                          subW);
            if(subRect.contains(e->pos()))
            {
                index = i;
                break;
            }
        }

        m_hoverIndex = index;
        if(m_hoverIndex < 0)
            this->unsetCursor();
        else
            this->setCursor(Qt::PointingHandCursor);//手指样式

        return;
    }

    if(m_selectedIndex < 0)
        return;

    auto *item = m_items[m_selectedIndex];
    item->duration = m_pressedDuration + (e->pos().x() - m_pressedPosX) * 1.0f / m_space * 100;

    int preDuration = -100;
    int nextDuration;

    if(m_selectedIndex > 0)
        preDuration = m_items[m_selectedIndex - 1]->duration;

    if(m_selectedIndex < m_items.length() - 1)
        nextDuration = m_items[m_selectedIndex + 1]->duration;
    else
        nextDuration = this->width() * 1.0f / m_space * 100 + 100;

    if(item->duration < preDuration + 100)
        item->duration = preDuration + 100;
    else if(item->duration > nextDuration - 100)
        item->duration = nextDuration - 100;

    update();
}

void ParticleTimeLineWidget::mouseReleaseEvent(QMouseEvent *e)
{
    e->accept();
    m_bPressed = false;
    update();
}

void ParticleTimeLineWidget::mouseDoubleClickEvent(QMouseEvent *e)
{
    //双击插入
    e->accept();
    if(m_selectedIndex >= 0)
        return;

    int duration = e->pos().x() * 1.0f / m_space * 100;

    //计算插入位置
    int index = -1;
    int len = m_items.length();
    for(int i=len-1; i>=0; --i)
    {
        if(duration > m_items[i]->duration)
        {
            index = i;
            break;
        }
    }

    ParticleItemData *d = new ParticleItemData;
    d->toNext = false;
    d->duration = duration;

    m_items.insert(index + 1, d);
    m_selectedIndex = index + 1;
    update();
}

void ParticleTimeLineWidget::paintEvent(QPaintEvent *e)
{
    (void)e;

    const int w = this->width();
    const int h = this->height();

    QPainter p;
    p.begin(this);

    p.setRenderHint(QPainter::Antialiasing);
    p.setRenderHint(QPainter::TextAntialiasing);

    //背景色
    p.fillRect(this->rect(), "gray");

    //绘制标尺
    const int rulerHeight = 32;
    drawRuler(&p, w, rulerHeight);

    //绘制Item
    int itemLen = m_items.length();
    {
        int dx = 0;
        for(int i=0; i<itemLen; ++i)
        {
            auto *item = m_items[i];

            dx = item->duration * 1.0f / 100 * m_space;
            QRect rect(dx - m_space / 2, rulerHeight + 20, m_space, 100);
            if(m_selectedIndex == i)
            {
                if(m_bPressed)//按下时绘制竖线
                {
                    p.save();
                    QPen pen = p.pen();
                    pen.setColor("#F0F0F0");
                    p.setPen(pen);
                    p.drawLine(dx, rulerHeight + 3, dx, h - 1);
                    p.restore();
                }
                p.fillRect(rect, "#007EC8");//绘制外框
            }
            else
                p.fillRect(rect, "#E6E6E6");//绘制外框

            //绘制文字
            p.drawText(rect, Qt::TextWrapAnywhere | Qt::AlignHCenter | Qt::AlignTop,
                       QString::number(i+1));

            //绘制中间区域是否选择
            const int subW = rect.width() - 4;
            QRect subRect(rect.x() + 2,
                          rect.y() + (rect.height() - subW) / 2,
                          subW,
                          subW);
            p.fillRect(subRect, "#31272F");
            if(item->toNext) {
                p.save();
                p.setPen("#F0F0F0");

                p.drawText(subRect, Qt::AlignCenter, "✓");
                //绘制连接线
                if(i<itemLen-1)
                {
                    auto *item2 = m_items[i + 1];
                    int dx2 = item2->duration * 1.0f / 100 * m_space;
                    QRect rect2(dx2 - m_space / 2, rulerHeight + 20, m_space, 100);

                    p.drawLine(rect.x() + rect.width(),
                               rect.y() + rect.height() / 2,
                               rect2.x(),
                               rect.y() + rect.height() / 2);
                }

                p.restore();
            }

        }
    }

    p.save();
    {
        QPen pen = p.pen();
        pen.setWidth(2);
        pen.setColor("#F0F0F0");
        p.setPen(pen);
        //绘制预览结束时间点
        m_previewEndDuration = 6400;
        int tx = m_previewEndDuration * 1.0f / 100 * m_space;
        p.drawLine(tx, rulerHeight + 3, tx, h - 1);
    }
    p.restore();

    p.end();
}

void ParticleTimeLineWidget::drawRuler(QPainter *p, int width, int height)
{
    int rectX = 0;
    int rectIndex = 0;


    p->drawRect(1, 1, width, height);

    while(1)
    {
        rectX = m_space * rectIndex;
        if(rectX > width)
            break;
        if(rectIndex % 5 == 0)
        {
            p->drawLine(rectX, 0, rectX, height);

            if(rectIndex % 2 == 0)
            {
                p->drawText(rectX + 4, 0, m_space*5, height,
                            Qt::AlignLeft | Qt::AlignVCenter,
                            QString("%1 ms").arg(100 * rectIndex));
            }
        }
        else
        {
            p->drawLine(rectX, height-6, rectX, height);
        }
        ++rectIndex;
    }

    p->save();
    {
        QPen pen = p->pen();
        pen.setWidth(2);
        pen.setColor("#F47C04");
        p->setPen(pen);

        //m_curDuration转为坐标
        m_curDuration = 5250;
        int tx = m_curDuration * m_space / 100 ;
        p->drawLine(tx, 0, tx, height);
    }
    p->restore();
}
